/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#pragma once

#include <memory>
#include <string>

#include "cyber/class_loader/class_loader.h"
#include "cyber/component/timer_component.h"

#include "modules/canbus/proto/chassis.pb.h"
#include "modules/common/monitor_log/monitor_log_buffer.h"
#include "modules/control/proto/control_cmd.pb.h"
#include "modules/control/proto/control_conf.pb.h"
#include "modules/control/proto/pad_msg.pb.h"
#include "modules/localization/proto/localization.pb.h"
#include "modules/planning/proto/planning.pb.h"

#include "modules/common/util/util.h"
#include "modules/control/controller/controller_agent.h"

/**
 * @namespace apollo::control
 * @brief apollo::control
 */
namespace apollo
{
    namespace control
    {

        using apollo::cyber::Reader;
        using apollo::cyber::Writer;
        /**
 * @class Control
 *
 * @brief control module main class, it processes localization, chassis, and
 * pad data to compute throttle, brake and steer values.
 */
        class ControlComponent final : public apollo::cyber::TimerComponent
        {
            friend class ControlTestBase;

        public:
            ControlComponent();
            bool Init() override; //函数重载  //重载其基类中的同名函数

            bool Proc() override; //函数重载  //重载其基类中的同名函数

            struct LocalView
            {
                canbus::Chassis chassis;
                planning::ADCTrajectory trajectory;
                localization::LocalizationEstimate localization;
            };

        public:
            // Upon receiving pad message
            void OnPad(const std::shared_ptr<apollo::control::PadMessage> &pad);

            void OnChassis(const std::shared_ptr<apollo::canbus::Chassis> &chassis);

            void OnPlanning(
                const std::shared_ptr<apollo::planning::ADCTrajectory> &trajectory);

            void OnLocalization(
                const std::shared_ptr<apollo::localization::LocalizationEstimate>
                    &localization);

            // Upon receiving monitor message
            void OnMonitor(
                const apollo::common::monitor::MonitorMessage &monitor_message);

            common::Status ProduceControlCommand(
                apollo::control::ControlCommand *control_command);
            common::Status CheckInput(LocalView *local_view);
            common::Status CheckTimestamp(const LocalView &local_view);
            common::Status CheckPad();

        public:
            ControlConf control_conf_;
            LocalView local_view_;
            ControllerAgent controller_agent_;

            double init_time_ = 0.0;

            localization::LocalizationEstimate latest_localization_;
            canbus::Chassis latest_chassis_;
            planning::ADCTrajectory latest_trajectory_;
            PadMessage pad_msg_;
            common::Header latest_replan_trajectory_header_;

            bool estop_ = false;
            std::string estop_reason_;
            bool pad_received_ = false;

            unsigned int status_lost_ = 0;
            unsigned int status_sanity_check_failed_ = 0;
            unsigned int total_status_lost_ = 0;
            unsigned int total_status_sanity_check_failed_ = 0;

            std::mutex mutex_;

            std::shared_ptr<Reader<apollo::canbus::Chassis>> chassis_reader_;
            std::shared_ptr<Reader<apollo::control::PadMessage>> pad_msg_reader_;
            std::shared_ptr<Reader<apollo::localization::LocalizationEstimate>>
                localization_reader_;
            std::shared_ptr<Reader<apollo::planning::ADCTrajectory>> trajectory_reader_;
            std::shared_ptr<Writer<apollo::control::ControlCommand>> control_cmd_writer_;
            common::monitor::MonitorLogBuffer monitor_logger_buffer_;
        };

        CYBER_REGISTER_COMPONENT(ControlComponent)
    } // namespace control
} // namespace apollo
